(addrs)[(i)].prefix > 64)
static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info);
-static void apply_lease(struct dhcp_assignment *a, bool add);
-static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b);
+static void apply_lease(struct dhcpv6_lease *a, bool add);
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_lease *b);
static void handle_addrlist_change(struct netevent_handler_info *info);
-static void start_reconf(struct dhcp_assignment *a);
-static void stop_reconf(struct dhcp_assignment *a);
+static void start_reconf(struct dhcpv6_lease *a);
+static void stop_reconf(struct dhcpv6_lease *a);
static void valid_until_cb(struct uloop_timeout *event);
static struct netevent_handler dhcpv6_netevent_handler = { .cb = dhcpv6_netevent_cb, };
static uint32_t serial = 0;
static uint8_t statemd5[16];
+static struct dhcpv6_lease *
+dhcpv6_alloc_lease(size_t extra_len)
+{
+ struct dhcpv6_lease *a = calloc(1, sizeof(*a) + extra_len);
+
+ if (!a)
+ return NULL;
+
+ INIT_LIST_HEAD(&a->head);
+ INIT_LIST_HEAD(&a->lease_cfg_list);
+
+ return a;
+}
+
+void dhcpv6_free_lease(struct dhcpv6_lease *a)
+{
+ list_del(&a->head);
+ list_del(&a->lease_cfg_list);
+
+ if (a->managed_sock.fd.registered) {
+ ustream_free(&a->managed_sock.stream);
+ close(a->managed_sock.fd.fd);
+ }
+
+ if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD))
+ apply_lease(a, false);
+
+ if (a->fr_cnt)
+ stop_reconf(a);
+
+ free(a->managed);
+ free(a->hostname);
+ free(a);
+}
+
int dhcpv6_ia_init(void)
{
uloop_timeout_set(&valid_until_timeout, 1000);
enable = enable && (iface->dhcpv6 == MODE_SERVER);
if (enable) {
- struct dhcp_assignment *border;
+ struct dhcpv6_lease *border;
if (list_empty(&iface->ia_assignments)) {
- border = alloc_assignment(0);
+ border = dhcpv6_alloc_lease(0);
if (!border) {
warn("Failed to alloc border on %s", iface->name);
border->length = 64;
list_add(&border->head, &iface->ia_assignments);
} else
- border = list_last_entry(&iface->ia_assignments, struct dhcp_assignment, head);
+ border = list_last_entry(&iface->ia_assignments, struct dhcpv6_lease, head);
set_border_assignment_size(iface, border);
} else {
- struct dhcp_assignment *c;
+ struct dhcpv6_lease *c;
while (!list_empty(&iface->ia_assignments)) {
- c = list_first_entry(&iface->ia_assignments, struct dhcp_assignment, head);
- free_assignment(c);
+ c = list_first_entry(&iface->ia_assignments, struct dhcpv6_lease, head);
+ dhcpv6_free_lease(c);
}
}
}
-static inline bool valid_prefix_length(const struct dhcp_assignment *a, const uint8_t prefix_length)
+static inline bool valid_prefix_length(const struct dhcpv6_lease *a, const uint8_t prefix_length)
{
return (a->managed_size || a->length > prefix_length);
}
IOV_TOTAL
};
-static int send_reconf(struct dhcp_assignment *assign)
+static int send_reconf(struct dhcpv6_lease *assign)
{
struct interface *iface = assign->iface;
struct dhcpv6_client_header hdr = {
memcpy(clientid.data, assign->clid_data, assign->clid_len);
- struct iovec iov[IOV_MAX] = {
+ struct iovec iov[IOV_TOTAL] = {
[IOV_HDR] = { &hdr, sizeof(hdr) },
[IOV_SERVERID] = { &serverid, sizeof(serverid) },
[IOV_CLIENTID] = { &clientid, sizeof(clientid) },
return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, iov, ARRAY_SIZE(iov), iface);
}
-static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a)
-{
- if (a->managed_sock.fd.registered) {
- ustream_free(&a->managed_sock.stream);
- close(a->managed_sock.fd.fd);
- }
-
- if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD))
- apply_lease(a, false);
-
- if (a->fr_cnt)
- stop_reconf(a);
-
- free(a->managed);
-}
-
static void in6_copy_iid(struct in6_addr *dest, uint64_t iid, unsigned n)
{
uint64_t iid_be = htobe64(iid);
return addr;
}
-void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c,
+void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcpv6_lease *c,
time_t now, dhcpv6_binding_cb_handler_t func, void *arg)
{
struct odhcpd_ipaddr *addrs = (c->managed) ? c->managed : iface->addr6;
struct write_ctxt {
FILE *fp;
md5_ctx_t md5;
- struct dhcp_assignment *c;
+ struct dhcpv6_lease *c;
struct interface *iface;
char *buf;
int buf_len;
}
}
-static void __apply_lease(struct dhcp_assignment *a,
+static void __apply_lease(struct dhcpv6_lease *a,
struct odhcpd_ipaddr *addrs, ssize_t addr_len, bool add)
{
if (a->flags & OAF_DHCPV6_NA)
}
}
-static void apply_lease(struct dhcp_assignment *a, bool add)
+static void apply_lease(struct dhcpv6_lease *a, bool add)
{
struct interface *iface = a->iface;
struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6;
}
/* Set border assignment size based on the IPv6 address prefixes */
-static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b)
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_lease *b)
{
time_t now = odhcpd_time();
int minprefix = -1;
static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
{
struct ustream_fd *fd = container_of(s, struct ustream_fd, stream);
- struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock);
+ struct dhcpv6_lease *c = container_of(fd, struct dhcpv6_lease, managed_sock);
time_t now = odhcpd_time();
bool first = c->managed_size < 0;
}
if (first && c->managed_size == 0)
- free_assignment(c);
+ dhcpv6_free_lease(c);
else if (first)
c->valid_until = now + 150;
}
static void managed_handle_pd_done(struct ustream *s)
{
struct ustream_fd *fd = container_of(s, struct ustream_fd, stream);
- struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock);
+ struct dhcpv6_lease *c = container_of(fd, struct dhcpv6_lease, managed_sock);
c->valid_until = odhcpd_time() + 15;
c->fr_cnt = 1;
}
-static bool assign_pd(struct interface *iface, struct dhcp_assignment *assign)
+static bool assign_pd(struct interface *iface, struct dhcpv6_lease *assign)
{
- struct dhcp_assignment *c;
+ struct dhcpv6_lease *c;
if (iface->dhcpv6_pd_manager[0]) {
int fd = usock(USOCK_UNIX | USOCK_TCP, iface->dhcpv6_pd_manager, NULL);
return false;
}
-static bool assign_na(struct interface *iface, struct dhcp_assignment *a)
+static bool assign_na(struct interface *iface, struct dhcpv6_lease *a)
{
- struct dhcp_assignment *c;
+ struct dhcpv6_lease *c;
uint64_t pool_start = 0x100;
uint64_t pool_end = (iface->dhcpv6_hostid_len >= 64) ? UINT64_MAX : ((1ULL << iface->dhcpv6_hostid_len) - 1);
uint64_t pool_size = pool_end - pool_start + 1;
static void handle_addrlist_change(struct netevent_handler_info *info)
{
struct interface *iface = info->iface;
- struct dhcp_assignment *c, *d, *border = list_last_entry(
- &iface->ia_assignments, struct dhcp_assignment, head);
+ struct dhcpv6_lease *c, *d, *border = list_last_entry(
+ &iface->ia_assignments, struct dhcpv6_lease, head);
struct list_head reassign = LIST_HEAD_INIT(reassign);
time_t now = odhcpd_time();
apply_lease(c, true);
if (c->accept_fr_nonce && c->fr_cnt == 0) {
- struct dhcp_assignment *a;
+ struct dhcpv6_lease *a;
start_reconf(c);
}
while (!list_empty(&reassign)) {
- c = list_first_entry(&reassign, struct dhcp_assignment, head);
+ c = list_first_entry(&reassign, struct dhcpv6_lease, head);
list_del_init(&c->head);
if (!assign_pd(iface, c))
- free_assignment(c);
+ dhcpv6_free_lease(c);
}
dhcpv6_ia_write_statefile();
static void reconf_timeout_cb(struct uloop_timeout *event)
{
- struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer);
+ struct dhcpv6_lease *a = container_of(event, struct dhcpv6_lease, fr_timer);
if (a->fr_cnt > 0 && a->fr_cnt < DHCPV6_REC_MAX_RC) {
send_reconf(a);
stop_reconf(a);
}
-static void start_reconf(struct dhcp_assignment *a)
+static void start_reconf(struct dhcpv6_lease *a)
{
uloop_timeout_set(&a->fr_timer,
DHCPV6_REC_TIMEOUT << a->fr_cnt);
send_reconf(a);
}
-static void stop_reconf(struct dhcp_assignment *a)
+static void stop_reconf(struct dhcpv6_lease *a)
{
uloop_timeout_cancel(&a->fr_timer);
a->fr_cnt = 0;
time_t now = odhcpd_time();
avl_for_each_element(&interfaces, iface, avl) {
- struct dhcp_assignment *a, *n;
+ struct dhcpv6_lease *a, *n;
if (iface->dhcpv6 != MODE_SERVER)
continue;
list_for_each_entry_safe(a, n, &iface->ia_assignments, head) {
if (a->clid_len > 0 && !INFINITE_VALID(a->valid_until) && a->valid_until < now)
- free_assignment(a);
+ dhcpv6_free_lease(a);
}
}
uloop_timeout_set(event, 1000);
}
static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status,
- const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a,
+ const struct dhcpv6_ia_hdr *ia, struct dhcpv6_lease *a,
struct interface *iface, bool request)
{
struct dhcpv6_ia_hdr o_ia = {
}
static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now,
- const char *duidbuf, bool is_pd, struct dhcp_assignment *a, int code)
+ const char *duidbuf, bool is_pd, struct dhcpv6_lease *a, int code)
{
const char *type = "UNKNOWN";
const char *status = "UNKNOWN";
duidbuf, iface->name, status, leasebuf);
}
-static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a,
+static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcpv6_lease *a,
struct interface *iface)
{
struct odhcpd_ipaddr *addrs = (a && a->managed) ? a->managed : iface->addr6;
ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface,
const struct sockaddr_in6 *addr, const void *data, const uint8_t *end)
{
- struct dhcp_assignment *first = NULL;
+ struct dhcpv6_lease *first = NULL;
const struct dhcpv6_client_header *hdr = data;
time_t now = odhcpd_time();
uint16_t otype, olen, clid_len = 0;
}
/* Find an existing assignment */
- struct dhcp_assignment *c, *a = NULL;
+ struct dhcpv6_lease *c, *a = NULL;
list_for_each_entry(c, &iface->ia_assignments, head) {
/* If we're looking for a PD, is this a PD? */
if (is_pd && !(c->flags & OAF_DHCPV6_PD))
* already knows or doesn't care about the old assignment.
*/
stop_reconf(c);
- free_assignment(c);
+ dhcpv6_free_lease(c);
goto proceed;
}
continue;
}
if (lease_cfg && a && a->lease_cfg != lease_cfg) {
- free_assignment(a);
+ dhcpv6_free_lease(a);
a = NULL;
}
if ((!iface->no_dynamic_dhcp || (lease_cfg && is_na)) &&
(iface->dhcpv6_pd || iface->dhcpv6_na)) {
/* Create new binding */
- a = alloc_assignment(clid_len);
+ a = dhcpv6_alloc_lease(clid_len);
if (a) {
a->clid_len = clid_len;
a->assigned_subnet_id = reqhint;
a->valid_until = now;
a->preferred_until = now;
- a->dhcp_free_cb = dhcpv6_ia_free_assignment;
a->iface = iface;
a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA);
if (lease_cfg->leasetime)
a->leasetime = lease_cfg->leasetime;
- list_add(&a->lease_cfg_list, &lease_cfg->assignments);
+ list_add(&a->lease_cfg_list, &lease_cfg->dhcpv6_leases);
a->lease_cfg = lease_cfg;
}
apply_lease(a, true);
} else if (!assigned && a && a->managed_size == 0) {
/* Cleanup failed assignment */
- free_assignment(a);
+ dhcpv6_free_lease(a);
a = NULL;
}
} else if (hdr->msg_type == DHCPV6_MSG_RENEW ||